/*
**NCS message communication between the ncs's processs including
**ncs client and ncs serv.
**This module provide the interface of processing the message
**It receives the ncs client's messages,or send messages to ncs
**client process. It uses the unix socket to finish this functions. 
**
**Copyright (C) 2016-1 andisat <www.andisat.com>
**
**Author: andisat
**Date:2016-1
**
*/
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include "ncs_list.h"
#include "ncs_log.h"
#include "ncs_network.h"
#include "ncs_fsm.h"
#include "ncs_cfg.h"
#include "ncs_sig.h"
#include "ncs_serv.h"
#include "ncs_msg.h"
#include "ncs_resmng.h"
#include "ncs_nmspacket.h"
#include "event.h"

#define PACKET_ADD_AND_SEND(x,y) \
if(state==TRUE)\
{\
    if((len + typelen + TLV_HEAD_LEN) > PACKET_PDU_MAX)\
    {\
        ncs2dev_send_cfg(ncs,dev,pinfo,len);\
        memset(pinfo,0,PACKET_PDU_MAX);\
        len = 0;\
    }\
    ptlv=(struct tlv_hdr *)pinfo;\
    ptlv->type=(x);\
    ptlv->len=htons(typelen);\
    memcpy((ptlv+1),(y),typelen);\
    pinfo += (TLV_HEAD_LEN+typelen);\
    len += (typelen + TLV_HEAD_LEN);\
}\

void dump_msg(char *pmsg,int bytes)
{
    struct msg_hdr *phdr;
    char *pinfo;
    char buff[50]={0};

    if(!pmsg)
        return;
    else
        phdr=(struct msg_hdr *)pmsg;

    if(bytes < sizeof(struct msg_hdr))
        printf("the message is error");

    printf("message:  Type: %02X  Len: %d \n",
            phdr->type,phdr->len);
    
    int j=0;
    pinfo=(char *)(phdr+1);
    bytes=bytes-sizeof(struct msg_hdr);
    for(int i=0;i<bytes;i++)
    {
        if(j==8){
            j = 0;
            printf(" %02X \n ",*pinfo);
        }
        else{
            j ++;
            printf(" %02X ",*pinfo);
        }
        pinfo ++;
    }
    
    return;
}

/* The interface of sending messages to ncs client process*/
int ncs_sendmsg(int fd,void *buff,int nbytes)
{
    int bytes;
    
    if(NULL==buff || 0==nbytes)
        return -1;
    
    dump_msg(buff,nbytes);
    
    bytes=write(fd,buff,nbytes);
    if(bytes != nbytes)
    {
        if(-1 == bytes)
            ncs_log(ERR,"write fd(%d) error %s ",fd,strerror(errno));
        else
            ncs_log(ERR,"write data %d bytes,but need write %d bytes",
                            bytes,nbytes);

        return -1;
    }

    return 0;
}


int ncs_send_rdcfg_finish_msg(int fd)
{
    char msg[3];

    struct msg_hdr *pmsg=(struct msg_hdr *)msg;
    pmsg->type = __NCS2NMS_RDCFG_FINISH_MSG__;
    pmsg->len = 1;
   
    msg[3] = 1;
    
    return ncs_sendmsg(fd,(void*)msg,4);
}

int ncs2nms_send_report_msg(int fd,char *buff,int bytes)
{
    int len,ret=0;
    struct msg_hdr *pmsg;
    
    if(!buff)
        return -1;
    
    len=bytes+MSG_HEAD_LEN;
    if(pmsg=(struct msg_hdr *)malloc(len))
        memset(pmsg,0,len);
    else
    {
        ncs_log(ERR,"%s malloc memory failure",__func__);
        return -1;
    }
        
    pmsg->type = __NCS2NMS_REPORT_MSG__;
    pmsg->len = bytes;
    memcpy((pmsg+1),buff,bytes);
    
    if(ncs_sendmsg(fd,(void*)pmsg,len))
        ncs_log(ERR,"%s ncs send report message failure",__func__);
    
    free(pmsg);
    return 0;
}

void ncs2nms_report_devstate(struct dev_obj *dev)
{
    int msglen;
    char *pmsg;
    struct _STR_DEV_ID_ *pdevId;
    struct _STR_DEV_STATUS_ *pdevStatus;

    msglen=sizeof(struct _STR_DEV_STATUS_)+sizeof(struct _STR_DEV_ID_); 
    if(pmsg=(char *)malloc(msglen))
        memset(pmsg,0,msglen);
    else
        return;

    pdevId=(struct _STR_DEV_ID_ *)pmsg;
    pdevId->devType=dev->type;
    pdevId->devId=htonl(dev->devId);
    
    pdevStatus=(struct _STR_DEV_STATUS_ *)(pdevId+1);
    //pdevStatus->devId=htonl(dev->ip);
    pdevStatus->status=dev->state;
    
    ncs2nms_send_report_msg(g_ncs_base.client_fd,pmsg,msglen);

    free(pmsg);

    return;
}

int get_cfg_pp_dev(struct dev_obj *pp)
{
    int cnt;

    
}

void ncs_get_pp_from_db(struct ncs_object *ncs)
{
    int cnt;
    struct dev_obj *pp;
    struct dev_set *ppset;
    pNCS_PP_INFO p_ppinfo;
    
    if(cnt=get_cfg_pp_info(p_ppinfo))
    {
        ppset=ncs->pp_set;
        ppset->sum++;

        for(int i=0;i<cnt;i++)
        {
            if(!(pp=build_dev()))
                return;

            pp->devId=p_ppinfo->IP;
            pp->type=DEV_TYPE_NCS;
            pp->ip=p_ppinfo->IP;
            /*To do: set the dev's port*/
            //pp->port=p_ppinfo->
            pp->state=p_ppinfo->State;            
        }
        
        if(pp->state == ONLINE)
            ppset->count++;
        
        if(ppset->count)
            ncs_start_dev_poll_event(ncs, pp);
        
        ncs_add_dev(ppset->dev_list, pp);
        p_ppinfo++;
    }
    
    if(cnt)
        free(p_ppinfo);
    
    return;
}

void ncs_get_sig_from_db(struct ncs_object *ncs)
{
    int cnt;
    struct dev_obj *psig;
    struct dev_set *sigset;
    pNCS_MODEM_INFO p_siginfo;

    cnt=get_cfg_sig_info(p_siginfo);
    for(int i=0;i<cnt;i++)
    {
        sigset=ncs->sig_set;
        sigset->sum++;
        
        if(!(psig=build_dev()))
            return;

        psig->devId=p_siginfo->DevID;
        psig->type=DEV_TYPE_SIGEMS;
        psig->ip=p_siginfo->IP;
        psig->state=p_siginfo->State;
        psig->flag=p_siginfo->DevFlag;
        memcpy(psig->devSN,p_siginfo->DevSN,DEV_SN_MAXLEN);
        memcpy(psig->name,p_siginfo->Name,DEV_NAME_MAXLEN);
            
        if(psig->state == ONLINE)
            sigset->count++;
        
        if(sigset->count)
        {
            ncs_start_dev_poll_event(ncs, psig);
            ncs_start_send_Ib_event(ncs, psig);
        }

        ncs_add_dev(sigset->dev_list, psig);
        p_siginfo++;
    }
    
    if(cnt)
        free(p_siginfo);
    
    return;
}

void ncs_get_rx_from_db(struct ncs_object *ncs)
{
    int cnt;
    struct dev_obj *prx;
    struct dev_set *rxset;
    pNCS_MODEM_INFO p_rxinfo;

    cnt=get_cfg_rx_info(p_rxinfo);
    for(int i=0;i<cnt;i++)
    {
        rxset=ncs->sig_set;
        rxset->sum++;

        if(!(prx=build_dev()))
            return;
                
        prx->devId=p_rxinfo->DevID;
        prx->type=DEV_TYPE_RXEMS;
        prx->ip=p_rxinfo->IP;
        prx->state=p_rxinfo->State;
        prx->flag=p_rxinfo->DevFlag;
        memcpy(prx->devSN,p_rxinfo->DevSN,DEV_SN_MAXLEN);
        memcpy(prx->name,p_rxinfo->Name,DEV_NAME_MAXLEN);
        
        if(prx->state == ONLINE)
            rxset->count++;
        
        if(rxset->count)
            ncs_start_dev_poll_event(ncs, prx);

        ncs_add_dev(rxset->dev_list, prx);
        p_rxinfo++;
    }

    if(cnt)
        free(p_rxinfo);
    
    return;
}

void ncs_get_rcst_from_db(struct ncs_object *ncs)
{
    int cnt;
    struct dev_obj *prcst;
    struct dev_set *rcstset;
    pNCS_MODEM_INFO p_rcstinfo;

    cnt=get_cfg_rcst_info(p_rcstinfo);
    for(int i=0;i<cnt;i++)
    {
        rcstset=ncs->sig_set;
        rcstset->sum++;

        if(!(prcst=build_dev()))
            return;
                
        prcst->devId=p_rcstinfo->DevID;
        prcst->type=DEV_TYPE_RCST;
        prcst->ip=p_rcstinfo->IP;
        prcst->state=p_rcstinfo->State;
        prcst->flag=p_rcstinfo->DevFlag;
        memcpy(prcst->devSN,p_rcstinfo->DevSN,DEV_SN_MAXLEN);
        memcpy(prcst->name,p_rcstinfo->Name,DEV_NAME_MAXLEN);
        
        if(dev_if_online(prcst))
            rcstset->count++;
        
        if(rcstset->count)
            ncs_start_dev_poll_event(ncs, prcst);

        ncs_add_dev(rcstset->dev_list, prcst);
        p_rcstinfo++;
    }
    
    if(cnt)
        free(p_rcstinfo);
    
    return;
}

void ncs_get_dev_from_db(struct ncs_object *ncs)
{
    ncs_get_pp_from_db(ncs);
    ncs_get_sig_from_db(ncs);
    ncs_get_rx_from_db(ncs);
    ncs_get_rcst_from_db(ncs);

    return;
}

void ncs_get_cfginfo_from_db(struct ncs_object *ncs)
{
    NCS_INFO ncsinfo;
    
    if(!ncs)
        return;

    if(get_cfg_ncs_info(&ncsinfo) > 0)
    {
        ncs->servd_ip=ncsinfo.IP;
        ncs->devId=ncsinfo.IP;
    }
    
    return;
}

/*To do: to process the configure parameters of ncs dev*/
int ncs_cfg_process(struct ncs_object *ncs,
        int devId,char *pinfo,int cnt)
{
    ncs_log(ERR,"%s receive the ncs configure message",__func__);
    return 0;
}

struct dev_obj *ncs_add_pp(struct ncs_object *ncs,int devId)
{
    struct dev_obj *pp;
    struct dev_set *ppset;
    
    if(!ncs)
        return NULL;

    ppset=ncs->pp_set;
    if(NULL == (pp=build_dev()))
        return NULL;
    
    pp->type=DEV_TYPE_PP;
    pp->devId=devId;
    pp->ip=devId;
    pp->state = OFFLINE;
    ppset->sum += 1;
    ncs_add_dev(ppset->dev_list,pp);
    
    return pp;
}

void pp_cfg_network(struct ncs_object *ncs,
    struct dev_obj *pp,char flag)
{
    int ret;
    struct dev_obj dev;
    struct dev_set *ppset=ncs->pp_set;
    
    if(flag & CFG_FLAG_ADD)
    {
        dev.ip=pp->ip;
        if(-1 == get_pp_by_ip_flag(&dev,(flag|CFG_FLAG_ID)))
            ncs_log(ERR,"there is pp not exist in database");
    }
    else if(flag & CFG_FLAG_DEL)
        ncs_del_pp(ncs,pp);         /*delete pp including deleting pp from database */
    else if(flag & CFG_FLAG_UPDATE)
    {
        if(-1 == get_pp_by_ip_flag(&dev,flag))
            ncs_log(ERR,"the update pp dev don't exist");
        else if(pp->ip != dev.ip)
        {
            pp->ip=dev.ip;
            pp->devId=dev.ip;
            
            if(pp->state==ONLINE)
            {
                pp_fsm_change(pp, POLL_PP_OFFLINE);
                ppset->count -= 1;
            }
            
            ncs_free_packetctl_list(pp);
        }
    }
    else
        ncs_log(ERR,"%s the flag(%d) is unknow",__func__,flag);
    
    return;
}


void pp_cfg_router(struct ncs_object *ncs,
    struct dev_obj *pp,int rc_id,char flag)
{
    int ret,len,typelen;
    char *pinfo;
    
    if(!ncs || !pp)
        return;
    
    if(FALSE == dev_if_online(pp))
        return;

    if(NULL==(pinfo=(char *)malloc(PACKET_PDU_MAX)))
        return;
         
    if((CFG_FLAG_ADD & flag) || (CFG_FLAG_DEL & flag))
    {
        struct _STR_ADD_ROUTER_ *prouter=NULL;
            ret=get_cfg_dev_router_by_devId_rcid_flag(pp->devId,rc_id,prouter,&len,(flag | CFG_FLAG_ID));
        if(ret == -1)
            goto END;
        else
        {
            typelen=packet_router_tlv(pinfo,prouter,len,flag);
            if(0 != typelen)
                ncs2dev_send_cfg(ncs,pp,pinfo,typelen);
        }            
    }
    else
        ncs_log(ERR,"the unknow flag %d",flag);
    
END:
    free(pinfo);
    return;
}

void pp_cfg_qosrule(struct ncs_object *ncs,
    struct dev_obj *pp,int rc_id,char flag)
{
    int ret,typelen;
    char *pinfo;
    
    if(!ncs || !pp)
        return;

    if(FALSE == dev_if_online(pp))
        return;
    
     if(NULL==(pinfo=(char *)malloc(PACKET_PDU_MAX)))
            return;
         
    if((CFG_FLAG_ADD & flag) || (CFG_FLAG_DEL & flag) || (CFG_FLAG_UPDATE & flag))
    {
        struct _STR_ADD_QOSRULE_ITEMS_ qosrule;
        ret=get_cfg_dev_qosrule_by_devId_rcid_flag(pp->devId,rc_id,
                    (void *)&qosrule,&typelen,(flag | CFG_FLAG_ID));
        if(ret == -1)
            goto STOP_SEND;
        else
        {             
            typelen = packet_qosrule_tlv(pinfo,&qosrule,typelen,flag);
            if(-1 != typelen)
                ncs2dev_send_cfg(ncs,pp,pinfo,typelen);
        }            
    }
    else
        ncs_log(ERR,"the unknow flag %d",flag);
    
STOP_SEND:
        free(pinfo);
        
    return;
}

void pp_cfg_vlan(struct ncs_object *ncs,
    struct dev_obj *pp,char flag)
{
    int ret,typelen;
    char *pinfo;
    
    if(!ncs || !pp)
        return;

    if(FALSE == dev_if_online(pp))
        return;
    
    if(NULL==(pinfo=(char *)malloc(PACKET_PDU_MAX)))
        return;

    if(CFG_FLAG_UPDATE & flag)
    {
        struct _STR_VLAN_ vlancfg;
        ret=get_cfg_dev_vlan(0,&vlancfg,&typelen);
        if(ret==-1)
            goto END;
        else
        {
            typelen=packet_add_vlan_tlv(pinfo, &vlancfg,typelen);
            if(0 != typelen)
                ncs2dev_send_cfg(ncs,pp,pinfo,typelen);
        }
    }
    else
        ncs_log(ERR,"the unknow flag %d",flag);

END:
    free(pinfo);
    return;
}


int pp_updatepars(struct ncs_object *ncs,
    struct dev_obj *pp,void *arg,int cnt)
{
    int i,rc_id;
    char type,flag;
    struct cfgmsg *pcfg;
    
    if(!ncs || !pp || !arg)
        return -1;
    
    pcfg=(struct cfgmsg *)arg;
    
    for(i = 0;i < cnt;i++)
    {
        type=pcfg->type;
        flag=pcfg->flag;
        rc_id=pcfg->rc_id;

        if((i+1)==cnt)
            flag |= CFG_FLAG_CLEAR;
        
        if(_IPADDR_ == type)
            pp_cfg_network(ncs,pp,flag);
        else if(_DEV_ID_ == type && flag == CFG_FLAG_DEL)
            ncs_del_pp(ncs,pp);
        else if(_ADD_ROUTER_ == type ||
                  _UPDATE_ROUTER_ == type ||
                  _DEL_ROUTER_ == type)
            pp_cfg_router(ncs,pp,rc_id,flag);
        else if(_ADD_QOSRULE_ITEMS_ == type ||
                _UPDATE_QOSRULE_ITEMS_ == type ||
                _DEL_QOSRULE_ITEMS_ == type)
            pp_cfg_qosrule(ncs,pp,rc_id,flag);
        else if(_VLAN_ == type)
            pp_cfg_vlan(ncs,pp,flag);
        else if(0)          /*To do: multicast TLV*/
            ;
        else       
            ncs_log(ERR,"%s the TLV(%d) is not included in PP",__func__,type);
    }
    
    return 0;
}

/*ncs process the pp's configure from ncs client message*/
int pp_cfg_process(struct ncs_object *ncs,
        int devId,char *pinfo,int cnt)
{
    struct dev_obj *pp;
    struct cfgmsg *pcfg;
    FSM_CALLFUNC func;

    if(!ncs || !pinfo)
        return -1;
    
    if(cnt <= 0)
        return -1;
    
    /*If the pp does not exist, else to add the pp*/
    if(NULL == (pp=ncs_find_pp(ncs, devId)))
    {
        pcfg=(struct cfgmsg *)(pinfo+sizeof(int));
        if(_IPADDR_ != pcfg->type || CFG_FLAG_ADD != pcfg->flag)
        {
            ncs_log(ERR,"%s the msg is wrong",__func__);
            return -1;
        }
        else
        {
            if(NULL == (pp=ncs_add_pp(ncs,devId)))
            {
                ncs_log(ERR,"%s add pp failure",__func__);
                return -1;
            }
        }
    }

    /*The pp exists, callback the FSM to process*/
    int event=RECEIVE_NMS_PARUPDATEPP_REQ;
    if(func=PP_FSM[pp->state][event].func)
        if(-1 != func(ncs,pp,pinfo,cnt))
            pp_fsm_change(pp,event);
    
    return 0;
}

struct dev_obj *ncs_add_modem(struct ncs_object *ncs,int devId,char type)
{
    struct dev_obj *dev;
    struct dev_set *devset;
    
    if(!ncs)
        return NULL;
    
    if(type == DEV_TYPE_SIGEMS)
        devset = ncs->pp_set;
    else if(type == DEV_TYPE_RXEMS)
        devset = ncs->rx_set;
    else if(type == DEV_TYPE_RCST)
        devset = ncs->rcst_set;
    else
        return NULL;
    
    if(NULL == (dev=build_dev()))
        return NULL;

    dev->type = type;
    dev->devId = devId;
    dev->state = OFFLINE;
    devset->sum += 1;
    
    ncs_add_dev(devset->dev_list,dev);
    
    return dev;
}

void modem_cfg_channel(struct ncs_object *ncs,struct dev_obj *dev,
        struct _STR_CHANNEL_ *pchannel,int *len,int rc_id,char flag)
{
    int ret;

    if(!ncs || !dev || !pchannel || !len)
        return;
    
    ret=get_cfg_dev_cha_by_devId_rcid_flag(ncs->devId,rc_id,pchannel,len,(CFG_FLAG_ID | flag));
    if(-1==ret)
        ncs_log(ERR,"get channel from database error");

    return;
}

void modem_cfg_channel_comm(struct ncs_object *ncs,struct dev_obj *dev,
        struct _STR_CHANNEL_COMM_ *pcha_comm,int *len,char flag)
{
    int ret;
    
    if(!ncs || !dev || !pcha_comm || !len)
        return;

    ret=get_cfg_dev_channel_comm_by_devId_flag(ncs->devId, pcha_comm, len, (CFG_FLAG_ID | flag));
    if(-1==ret)
        ncs_log(ERR,"get channel common from database error");
    
    return;
}

void modem_cfg_qos_rule(struct ncs_object *ncs,struct dev_obj *dev,
        void *pqosrule,int *len,int rc_id,char flag)
{
    int ret;
    if(!ncs || !dev || !pqosrule || !len)
        return;

    ret=get_cfg_dev_qosrule_by_devId_rcid_flag(ncs->devId, rc_id, pqosrule, len, (CFG_FLAG_ID | flag));
    if(-1==ret)
        ncs_log(ERR,"get qos rule from database error");
    
    return;
}

void modem_cfg_resource_rule(struct ncs_object *ncs,struct dev_obj *dev,
        struct _STR_RESOURCE_RULE_ITEMS_ *presource_rule,int *len,char flag)
{
    int ret;
    
    if(!ncs || !dev || !presource_rule || !len)
        return;

    *len = 0;
    if((CFG_FLAG_ADD & flag) || (CFG_FLAG_UPDATE & flag) || (CFG_FLAG_DEL & flag))
    {
        ret=get_cfg_dev_resource_rule_by_devId_flag(dev->devId,presource_rule,len,(CFG_FLAG_ID | flag));
        if(-1 == ret)
            ncs_log(ERR,"get resource rule from database error");
    }
    else
        ;
    
    return; 
}

void modem_cfg_resource_bod(struct ncs_object *ncs,struct dev_obj *dev,
        struct _STR_RESOURCE_BOD_ *presource_bod,int *len,char flag)
{
    int ret;
    
    if(!ncs || !dev || !len || !presource_bod)
        return;

    *len = 0;
    if((CFG_FLAG_ADD & flag) || (CFG_FLAG_UPDATE & flag))
    {
        ret=get_cfg_dev_resource_bod_by_devId_flag(dev->devId,presource_bod,len,(CFG_FLAG_ID | flag));
        if(-1 == ret)
            ncs_log(ERR,"get resource bod from database error");
    }
    else
        ;
    
    return; 
}

void modem_cfg_work_mode(struct ncs_object *ncs,struct dev_obj *dev,
        struct _STR_WORK_MODE_ *pworkmode,int *len,char flag)
{
    int ret;
    
    if((NULL==ncs) || (NULL==dev)
        || (NULL==pworkmode) || (NULL==len))
        return;

    *len = 0;
    if((CFG_FLAG_ADD & flag) || (CFG_FLAG_UPDATE & flag))
    {
        ret=get_cfg_dev_workmode_by_devId_flag(dev->devId,pworkmode,len,(CFG_FLAG_ID | flag));
        if(-1 == ret)
           ncs_log(ERR,"get workmode from database error");
    }
    else
        ;
    
    return; 
}

void modem_cfg_backup(struct ncs_object *ncs,struct dev_obj *dev,
        struct _STR_BACKUP_ *pbackup,int *len,char flag)
{
    int ret;
    
    if((NULL==ncs) || (NULL==dev)
        || (NULL==pbackup) || (NULL==len))
        return;

    *len = 0;
    if((CFG_FLAG_ADD & flag) || (CFG_FLAG_UPDATE & flag))
    {
        ret=get_cfg_dev_backup_by_devId_flag(dev->devId,pbackup,len,(CFG_FLAG_ID | flag));
        if(-1 == ret)
            ncs_log(ERR,"get backup from database error");
    }
    else
        ;
    
    return; 

}

void modem_cfg_system_op(struct ncs_object *ncs,struct dev_obj *dev,
        struct _STR_SYSTEM_OP_ *poperation,int *len,int rc_id)
{
    if(!ncs || !dev || !poperation || !len)
        return;

    poperation->operation = (rc_id & 0X000000FF);
    *len=sizeof(struct _STR_SYSTEM_OP_);

    return;
}

void modem_cfg_dev_name(struct ncs_object *ncs,struct dev_obj *dev,
        struct _STR_DEV_NAME_ *pname,int *len,char flag)
{
    int ret;
    
    if((NULL==ncs) || (NULL==dev)
        || (NULL==pname) || (NULL==len))
        return;

    *len = 0;
    if((CFG_FLAG_ADD & flag) || (CFG_FLAG_UPDATE & flag))
    {
        ret=get_cfg_dev_name_by_devId_flag(dev->devId,pname,len,(CFG_FLAG_ID | flag));
        if(-1 == ret)
            ncs_log(ERR,"get dev name from database error");
    }
    else
        ;
    
    return; 
}

void modem_cfg_gwip(struct ncs_object *ncs,struct dev_obj *dev,
        struct _STR_DEFAULT_GWIP_ *pgwip,int *len,char flag)
{
    int ret;
    
    if((NULL==ncs) || (NULL==dev)
        || (NULL==pgwip) || (NULL==len))
        return;

    *len = 0;
    if((CFG_FLAG_ADD & flag) || (CFG_FLAG_UPDATE & flag))
    {
        ret=get_cfg_gwip_by_devId_flag(dev->devId,pgwip,len,(CFG_FLAG_ID | flag));
        if(-1 == ret)
            ncs_log(ERR,"get devId from database error");
    }
    else
        ;
    
    return;   
}

void modem_cfg_ipaddr(struct ncs_object *ncs,struct dev_obj *dev,
        struct _STR_IPADDR_ *pipaddr,int *len,char flag)
{
    int ret;
    
    if((NULL==ncs) || (NULL==dev)
        || (NULL==pipaddr) || (NULL==len))
        return;

    *len = 0;
    if((CFG_FLAG_ADD & flag) || (CFG_FLAG_UPDATE & flag))
    {
        ret=get_cfg_ipaddr_by_devId_flag(dev->devId,pipaddr,len,(CFG_FLAG_ID | flag));
        if(-1 == ret)
            ncs_log(ERR,"get devId from database error");
    }
    else
        ;
    
    return;   
}

void modem_cfg_modem(struct ncs_object *ncs,struct dev_obj *dev,
    struct _STR_MODEM_ *pmodem_info,int *len,char flag)
{   
    int ret;
    
    if(NULL == ncs || NULL == dev || NULL == pmodem_info)
        return;

    *len=0; /*init len to 0*/
    if(CFG_FLAG_ADD & flag)
    {
        ret=get_modem_info_by_devId_flag(dev->devId,pmodem_info,len,(CFG_FLAG_ID | flag));
        if(-1 == ret)
            return;
    }
    else if(CFG_FLAG_UPDATE & flag)
    {
        ret=get_modem_info_by_devId_flag(dev->devId,pmodem_info,len,CFG_FLAG_ID);
        if(-1 == ret)
            return;
        /*To do: to be sure the items of authentication*/
        if(memcmp(pmodem_info->devSN,dev->devSN,DEV_SN_MAXLEN) 
            || (pmodem_info->ip != dev->ip))
        {
            
        }  
    }
    else if(CFG_FLAG_DEL & flag)
        ncs_del_modem(ncs,dev);
    else
        ;
    
    return;
}

/*modem update parameters or configures from NMS*/
int modem_updatepars(struct ncs_object *ncs,
        struct dev_obj *dev,void *arg,int cnt)
{
    int state;
    int typelen,rc_id,len=0;
    char type,flag,*pinfo;
    struct cfgmsg *pcfg;
    struct tlv_hdr *ptlv;
    
    if(!ncs || !dev || !arg)
        return -1;
    
    /*get the cnt and message of configure*/
    if(cnt <= 0)
        return -1;  
    
    pcfg=(struct cfgmsg *)arg;

    /*Apply memory for packet payload of configure,
    if the dev is on onlince*/
    if(dev_if_online(dev))
    {
        pinfo=(char *)malloc(PACKET_PDU_MAX);
        if(NULL == pinfo)
        {
            ncs_log(ERR,"apply for memory failure");
            return -1;
        }
        memset(pinfo,0,PACKET_PDU_MAX);
    }
        
    for(int i=0; i < cnt; i++)
    {
        type=pcfg->type;
        flag=pcfg->flag;
        rc_id=pcfg->rc_id;                      

        if((i+1) == cnt)
            flag |= CFG_FLAG_CLEAR;
        
        switch(type){
            case _DEV_ID_:
            {
                if(flag == CFG_FLAG_DEL){
                    ncs_del_modem(ncs, dev);
                    return 0;
                }
                break;
            }
            case _MODEM_:
            {
                struct _STR_MODEM_ modem_info;
                modem_cfg_modem(ncs,dev,&modem_info,&typelen,flag);
                PACKET_ADD_AND_SEND(_MODEM_,&modem_info)
                break;
            }
            case _IPADDR_:
            {
                struct _STR_IPADDR_ ipaddr;
                modem_cfg_ipaddr(ncs,dev,&ipaddr,&typelen,flag);
                PACKET_ADD_AND_SEND(_MODEM_,&ipaddr)
                break;
            }
            case _DEFAULT_GWIP_:
            {
                struct _STR_DEFAULT_GWIP_ gwip;
                modem_cfg_gwip(ncs,dev,&gwip,&typelen,flag);
                PACKET_ADD_AND_SEND(_DEFAULT_GWIP_,&gwip)
                break;
            }
            case _DEV_NAME_:
            {
                struct _STR_DEV_NAME_ devname;
                modem_cfg_dev_name(ncs,dev,&devname,&typelen,flag);
                PACKET_ADD_AND_SEND(_DEV_NAME_,&devname)
                break;
            }
            case _DEV_TIME_:
            {
                struct _STR_DEV_TIME_ devtime;
                devtime.time=time((time_t *)NULL);
                typelen=sizeof(struct _STR_DEV_TIME_);
                PACKET_ADD_AND_SEND(_DEV_TIME_,&devtime)
                break;
            }
            case _SYSTEM_OP_:
            {
                struct _STR_SYSTEM_OP_ system_opt;
                modem_cfg_system_op(ncs,dev,&system_opt,&typelen,rc_id);
                PACKET_ADD_AND_SEND(_BACKUP_,&system_opt)
                break;
            }
            case _BACKUP_:
            {
                struct _STR_BACKUP_ backup;
                modem_cfg_backup(ncs,dev,&backup,&typelen,flag);
                PACKET_ADD_AND_SEND(_BACKUP_,&backup)
                break;
            }
            case _WORK_MODE_:
            {
                struct _STR_WORK_MODE_ workmode;
                modem_cfg_work_mode(ncs,dev,&workmode,&typelen,flag);
                PACKET_ADD_AND_SEND(_WORK_MODE_,&workmode)
                break;
            }
            case _RESOURCE_BOD_:
            {
                struct _STR_RESOURCE_BOD_ resource_bod; 
                modem_cfg_resource_bod(ncs,dev,&resource_bod,&typelen,flag);
                PACKET_ADD_AND_SEND(_RESOURCE_BOD_,&resource_bod)
                break;
            }
            case _RESOURCE_RULE_ITEMS_:
            {
                struct _STR_RESOURCE_RULE_ITEMS_ resource_rule;     
                modem_cfg_resource_rule(ncs,dev,&resource_rule,&typelen,flag);
                PACKET_ADD_AND_SEND(_RESOURCE_RULE_ITEMS_,&resource_rule)
                break;
            }
            case _ADD_QOSRULE_ITEMS_:
            {
                struct _STR_ADD_QOSRULE_ITEMS_ add_qosrule;
                modem_cfg_qos_rule(ncs,dev,(void *)&add_qosrule,&typelen,rc_id,flag);
                PACKET_ADD_AND_SEND(_ADD_QOSRULE_ITEMS_,&add_qosrule)
                break;
            }
            case _UPDATE_QOSRULE_ITEMS_:
            {
                struct _STR_UPDATE_QOSRULE_ITEMS_ update_qosrule;
                modem_cfg_qos_rule(ncs,dev,(void *)&update_qosrule,&typelen,rc_id,flag);
                PACKET_ADD_AND_SEND(_UPDATE_QOSRULE_ITEMS_,&update_qosrule)
                break;
            }
            case _DEL_QOSRULE_ITEMS_:
            {
                struct _STR_DEL_QOSRULE_ITEMS_ del_qosrule;
                modem_cfg_qos_rule(ncs,dev,(void *)&del_qosrule,&typelen,rc_id,flag);
                PACKET_ADD_AND_SEND(_UPDATE_QOSRULE_ITEMS_,&del_qosrule)
                break;
            }
            case _CHANNEL_COMM_:
            {
                struct _STR_CHANNEL_COMM_ cha_comm;                
                modem_cfg_channel_comm(ncs,dev,&cha_comm,&typelen,flag);
                PACKET_ADD_AND_SEND(_CHANNEL_COMM_,&cha_comm)
                break;
            }
            case _CHANNEL_:
            {
                struct _STR_CHANNEL_ channel;
                modem_cfg_channel(ncs,dev,&channel,&typelen,rc_id,(CFG_FLAG_ID |flag));
                PACKET_ADD_AND_SEND(_CHANNEL_,&channel)
                break;
            }
            /*To do: router isn't required now*/
            /*To do: to add multicast */
            default:
                ncs_log(ERR,"%s the unknow type(%d) of TLV",__func__,type);
                break;
        }
    }   

    if(len != 0)
        ncs2dev_send_cfg(ncs,dev,pinfo,len);
    
    free(pinfo);   
    return 0;
}

int sig_cfg_process(struct ncs_object *ncs,
        int devId,char *pinfo,int cnt)
{
    struct dev_obj *sig;
    struct cfgmsg *pcfg;
    FSM_CALLFUNC func;

    if(!ncs || !pinfo)
        return -1;

    /*Check the cnt of cfgmsg,If the cnt <= 0,then return*/
    if(cnt <= 0)
        return -1;

    /*If the sig is not exist, check the type and flag of cfg,
    if the flag==CFG_FLAG_ADD && type==_MODEM_,then add 
    sig to ncs's sigset.*/
    if(NULL == (sig=ncs_find_sig(ncs,devId)))
    {
        pcfg=(struct cfgmsg *)pinfo;
        if(pcfg->type != _MODEM_ || pcfg->flag != CFG_FLAG_ADD)
        {
            ncs_log(ERR,"%s the dev is not exist",__func__);
            return -1;
        }
        
        if(NULL == (sig=ncs_add_modem(ncs,devId,DEV_TYPE_SIGEMS)))
            return -1;
    }

    /*The sig exists, callback the FSM to process*/
    int event=RECEIVE_NMS_PARUPDATESIG_REQ;
    if(func=SIG_FSM[sig->state][event].func)
        if(-1 != (func(ncs,sig,pinfo,cnt)))
            pp_fsm_change(sig,event);

    return 0;
}

int rx_cfg_process(struct ncs_object *ncs,
        int devId,char *pinfo,int cnt)
{
    struct dev_obj *rx;
    struct cfgmsg *pcfg;
    FSM_CALLFUNC func;

    if(!ncs || !pinfo)
        return -1;

    /*Check the cnt of cfgmsg,If the cnt <= 0,
    return this function*/
    if(cnt <= 0)
        return -1;

    /*If the rx is not exist, check the type and flag of cfg,
    if the flag==CFG_FLAG_ADD && type==_MODEM_,then add 
    sig to ncs's sigset.*/
    if(NULL == (rx=ncs_find_sig(ncs,devId)))
    {
        pcfg=(struct cfgmsg *)pinfo;
        if(pcfg->type != _MODEM_ || pcfg->flag != CFG_FLAG_ADD)
        {
            ncs_log(ERR,"%s the dev is not exist",__func__);
            return -1;
        }
        
        if(NULL == (rx=ncs_add_modem(ncs,devId,DEV_TYPE_RXEMS)))
            return -1;
    }

    /*The rx exists, callback the FSM to process*/
    int event=RECEIVE_NMS_PARUPDATERX_REQ;
    if(func=RX_FSM[rx->state][event].func)
        if(-1!=func(ncs,rx,pinfo,cnt))
            pp_fsm_change(rx,event);

    return 0;
}

int rcst_cfg_process(struct ncs_object *ncs,
        int devId,char *pinfo,int cnt)
{
    struct dev_obj *rcst;
    struct cfgmsg *pcfg;
    FSM_CALLFUNC func;

    if(!ncs || !pinfo)
        return -1;

    /*Check the cnt of cfgmsg,If the cnt >= 0,
    return this function*/
    if(cnt <= 0)
        return -1;

    /*If the rcst is not exist, check the type and flag of cfg,
    if the flag==CFG_FLAG_ADD && type==_MODEM_,then add 
    rcst to ncs's rcstset.*/
    if(NULL == (rcst=ncs_find_rcst(ncs,devId)))
    {
        pcfg=(struct cfgmsg *)pinfo;
        if(pcfg->type != _MODEM_ || pcfg->flag != CFG_FLAG_ADD)
        {
            ncs_log(ERR,"%s the dev(Id:%d) is not exist",__func__,devId);
            return -1;
        }
        
        if(NULL == (rcst=ncs_add_modem(ncs,devId,DEV_TYPE_RCST)))
            return -1;
    }
    
    int event=RECEIVE_NMS_PARUPDATERCST_REQ;
    if(func=RCST_FSM[rcst->state][event].func)
        if(-1!=func(ncs,rcst,pinfo,cnt))
            pp_fsm_change(rcst,event);

    return 0;
}


struct ncs_client_msg_func ncs_client_msg[__NCS_CLIENT_MSGTYPE_MAX__+1]=
{
    {0,NULL},
    {__NCS2NMS_RDCFG_FINISH_MSG__,NULL},
    {__NCS2NMS_REPORT_MSG__,NULL},
    {__NCS2NMS_CFGRESULT_REPORT_MSG__,NULL},
    {__NCS2NMS_LOGON_MSG__,ncs_logon_msg},
    {__NMS2NCS_LOGOFF_MSG__,ncs_logoff_rcst_msg},
    {__NMS2NCS_DEVCFG_MSG__,ncs_devcfg_msg},
    {__NMS2NCS_CARRIERLOCK_MSG__,ncs_carrierlock_msg},
    {__NMS2NCS_CARRIERLOCK_RELEASE_MSG__,ncs_carrierlock_rel_msg},
    {__NMS2NCS_RELEASE_RESOURCE_MSG__,ncs_rel_resource_msg},
    {0,NULL}
};
    
int ncs_logon_msg(char type,void *arg,void *buff)
{
    struct msg_hdr *pmsg;
    struct ncs_object *ncs=arg;
    char result;

    if(!ncs || !buff)
        return -1;

    pmsg=(struct msg_hdr *)buff;
    result=*(char *)(pmsg+1);
    if(result == 0)
    {
        ncs_log(INFO,"%s ncs auth faliure",__func__);
        free_ncs(ncs);
        exit(0);
    }
    else if(result == 1)
    {
        ncs->state = ONLINE;
        set_ncsfsm_state(ncs);
        ncs_get_cfginfo_from_db(ncs);    
        ncs_creat_serv(ncs);
        ncs_start_broadcast(ncs);
    }
    else
       ncs_log(WARN,"%s the result %d is unknow",__func__,type);
    
    return 0;  
}

int ncs_logoff_rcst_msg(char type,void *arg,void *buff)
{
    char result;
    int devId;
    struct msg_hdr *pmsg;
    struct dev_obj *rcst;
    struct ncs_object *ncs=arg;
    FSM_CALLFUNC func;
        
    if(!ncs || !buff)
        return -1;

    pmsg = (struct msg_hdr *)buff;
    if(pmsg->len <= 0)
        return -1;
    
    devId = *(int*)(pmsg+1);
    if(!(rcst=ncs_find_rcst(ncs,devId)))
    {
        struct _STR_CFG_RESULT_ *pcfgresult;
        int msglen=TLV_HEAD_LEN+sizeof(struct _STR_CFG_RESULT_);
        struct tlv_hdr *ptlv;
        if(ptlv=(struct tlv_hdr *)malloc(msglen))
            memset(ptlv,0,msglen);
        else
            return 0;
        
        ptlv->type=_CFG_RESULT_;
        ptlv->len=htons(msglen);
        pcfgresult=(struct _STR_CFG_RESULT_ *)(ptlv+1);    
        pcfgresult->devId = htonl(devId);
        pcfgresult->msg = htonl(__NMS2NCS_LOGOFF_MSG__);
        memcpy(pcfgresult->info,"RCST Not Exist",CFG_RESULT_INFO_MAX);
        
        ncs2nms_send_report_msg(ncs->client_fd,(char *)ptlv,msglen);  
        ncs_log(WARN,"%s %d %s",__func__,pcfgresult->devId,pcfgresult->info);
        free(ptlv);
        
        return 0;
    }

    int event=RECEIVE_NMS_LOGOFF_REQ;
    if(func = RCST_FSM[rcst->state][event].func)
        if(-1!=func(ncs,rcst,NULL,0))
            rcst_fsm_change(rcst,event);

    return 0;    
}

/*
process the dev configure parameters including add/
update/del the struct of cfg:                                                               
struct cfg_msg
{
    char devType;    
    int devId;
    int cnt;               is the count of the following struct
    struct info
    {
        char type;       is TLV's type
        char flag;
    }
}
*/
int ncs_devcfg_msg(char type,void *arg,void *buff)
{
    int devId,cnt;
    char msgtype,*pinfo;
    struct cfgmsg_hdr *pcfghdr;
    struct ncs_object *ncs=arg;
    struct msg_hdr *pmsg=buff;
    
    if(!ncs || !buff || pmsg->type != __NMS2NCS_DEVCFG_MSG__)
        return -1;
    
    if(pmsg->len <= 0)
        return -1;
    /*Get configure head info,if the count of cfg<=0,return;
    else callback functions to process by the type of dev.*/
    pcfghdr = (struct cfgmsg_hdr * )(pmsg+1);
    msgtype=pcfghdr->devType;
    devId=pcfghdr->devId;
    cnt=pcfghdr->cnt;
    
    if(pmsg->len != (sizeof(struct cfgmsg_hdr) 
        + cnt*sizeof(struct cfgmsg))){
        ncs_log(ERR,"%s the len(%d) of message is not right",__func__,pmsg->len);
        return -1;
    }
    
    pinfo = (char*)(pcfghdr+1); 
    
    switch(msgtype)
    {
        case DEV_TYPE_NCS:
                ncs_cfg_process(ncs,devId,pinfo,cnt);
                break;
        case DEV_TYPE_PP:
                pp_cfg_process(ncs,devId,pinfo,cnt);
                break;
        case DEV_TYPE_RXEMS:
                rx_cfg_process(ncs,devId,pinfo,cnt);
                break;
        case DEV_TYPE_SIGEMS:
                sig_cfg_process(ncs,devId,pinfo,cnt);
                break;
        case DEV_TYPE_RCST:
                rcst_cfg_process(ncs,devId,pinfo,cnt);
                break;
        default:
                ncs_log(WARN,"%s The %d is the unknow dev",__func__,type);
                break;
    }
    
    return 0;
}

int ncs_carrierlock_msg(char type,void *arg,void *buff)
{
    int msglen;
    FSM_CALLFUNC func;
    struct tlv_hdr *ptlv;
    struct msg_hdr *pmsg;
    struct dev_obj *rcst,*rx;
    struct ncs_object *ncs=arg;
    struct carrierLock_msg *pcarrierlock;
    struct _STR_CFG_RESULT_ *pcfgresult;
    
    if(!ncs || !buff )
        return -1;

    pmsg = (struct msg_hdr *)buff;
    if(pmsg->len <= 0)
        return -1;
    
    pcarrierlock = (struct carrierLock_msg *)(pmsg+1);
    if(!(rcst=ncs_find_rcst(ncs,pcarrierlock->txdevId))
        || !(rx=ncs_find_rx(ncs,pcarrierlock->rxdevId)))
        goto LOCK_ERR;
    
    if(CHECK_BIT(rcst->flag,DEV_FLAG_LOCK)
        || rcst->state == RCST_ONLINE_RELRES
        || rcst->state == RCST_OFFLINE_RELRES)
        goto LOCK_ERR;

    int event=RECEIVE_NMS_LOCKTXPATH_REQ;
    if(func=RCST_FSM[rcst->state][event].func)
        if(-1 != func(ncs,rcst,pcarrierlock,0))
            rcst_fsm_change(rcst,event);
        
LOCK_ERR:
    msglen=TLV_HEAD_LEN+sizeof(struct _STR_CFG_RESULT_);
    if(ptlv=(struct tlv_hdr *)malloc(msglen))
        memset(ptlv,0,msglen);
    else
        return 0;
        
    ptlv->type=_CFG_RESULT_;
    ptlv->len=htons(msglen);
    pcfgresult=(struct _STR_CFG_RESULT_ *)(ptlv+1);    
    pcfgresult->devId = htonl(pcarrierlock->rxdevId);
    pcfgresult->msg = htonl(__NMS2NCS_CARRIERLOCK_MSG__);
    memcpy(pcfgresult->info,"lock error",CFG_RESULT_INFO_MAX);

    ncs2nms_send_report_msg(ncs->client_fd,(char *)ptlv,msglen);  
    ncs_log(ERR,"%s lock failure %d %s",__func__,pcfgresult->devId,pcfgresult->info);
    free(ptlv);

    return 0;
}

int ncs_carrierlock_rel_msg(char type,void *arg,void *buff)
{
    struct dev_obj *dev;
    FSM_CALLFUNC proc;
    int msglen;
    struct tlv_hdr *ptlv;
    struct msg_hdr *pmsg;
    struct ncs_object *ncs=arg;
    struct _STR_CHANNEL_ID_ *ptxcha;
    struct _STR_CFG_RESULT_ *pcfgresult;

     if(!ncs || !buff)
        return -1;
     
     pmsg=(struct msg_hdr *)buff;
     if(pmsg->len <= 0)
        return -1;
     
    ptxcha = (struct _STR_CHANNEL_ID_ *)(pmsg+1);
    if(dev=ncs_find_rcst(ncs,ptxcha->devId))
    {
        if(!CHECK_BIT(dev->flag,DEV_FLAG_LOCK)
            || (dev->state == RCST_OFFLINE_RELRES)
            || (dev->state == RCST_ONLINE_RELRES)
            || (dev->state == RCST_ONLINE_OPENRX)
            || (PATH_FIRST != ptxcha->chaId))
            goto LOCKREL_ERR;

        int event=RECEIVE_NMS_LOCKREL_REQ;
        if(proc=RCST_FSM[dev->state][event].func)
            if(-1 != proc(ncs,dev,ptxcha,0))
                rcst_fsm_change(dev,event);
            
        return 0;
    }    

LOCKREL_ERR:    
    msglen=TLV_HEAD_LEN+sizeof(struct _STR_CFG_RESULT_);
    if(ptlv=(struct tlv_hdr *)malloc(msglen))
        memset(ptlv,0,msglen);
    else
        return 0;
    
    ptlv->type=_CFG_RESULT_;
    ptlv->len=htons(msglen);
    pcfgresult=(struct _STR_CFG_RESULT_ *)(ptlv+1);    
    pcfgresult->devId = htonl(ptxcha->devId);
    pcfgresult->msg = htonl(__NMS2NCS_CARRIERLOCK_RELEASE_MSG__);
    memcpy(pcfgresult->info,"lock release error",CFG_RESULT_INFO_MAX);

    ncs2nms_send_report_msg(ncs->client_fd,(char *)ptlv,msglen);  
    ncs_log(ERR,"%s lock release failure %d %s",__func__,pcfgresult->devId,pcfgresult->info);
    free(ptlv);

    return -1;   
}

int ncs_rel_resource_msg(char type,void *arg,void *buff)
{
    int ret,event;
    int msglen;
    struct dev_obj *dev;
    struct tlv_hdr *ptlv;
    struct ncs_object *ncs;
    struct msg_hdr *pmsg;
    struct _STR_CHANNEL_ID_ *pcha;
    struct _STR_CFG_RESULT_ *pcfgresult;
    FSM_CALLFUNC func;

    if(!ncs || !buff)
        return -1;
    
    ncs=(struct ncs_object *)arg;
    pmsg=(struct msg_hdr *)buff;        
    pcha=(struct _STR_CHANNEL_ID_ *)(pmsg+1);
    if(dev=ncs_find_rcst(ncs,pcha->devId))
    {
        if(PATH_FIRST != pcha->chaId)
            goto NotFind;

        event=RECEIVE_NMS_RELRCSTRES_REQ;
        if(func=RCST_FSM[dev->state][event].func)
            ret=func(ncs,dev,pcha,0);
        
        if(-1 != ret)
            rcst_fsm_change(dev,event);
    }
    else if(dev=ncs_find_rx(ncs,pcha->devId))
    {
        if(pcha->chaId > PATH_FOURTH || pcha->chaId < PATH_FIRST)
            goto NotFind;

        event=RECEIVE_NMS_RELRESRX_REQ;
        if(func=RCST_FSM[dev->state][event].func)
            ret=func(ncs,dev,pcha,sizeof(struct _STR_CHANNEL_ID_)); 
        
        if(-1 != ret)
            rcst_fsm_change(dev,event);
    }
    else
    {
NotFind:
        msglen=TLV_HEAD_LEN+sizeof(struct _STR_CFG_RESULT_);
        if(ptlv=(struct tlv_hdr *)malloc(msglen))
            memset(ptlv,0,msglen);
        else
            return 0;
        
        ptlv->type=_CFG_RESULT_;
        ptlv->len=htons(msglen);
        pcfgresult=(struct _STR_CFG_RESULT_ *)(ptlv+1);    
        pcfgresult->devId = htonl(pcha->devId);
        pcfgresult->msg = htonl(__NMS2NCS_RELEASE_RESOURCE_MSG__);
        memcpy(pcfgresult->info,"Devcha Not Exist",20);

        ncs2nms_send_report_msg(ncs->client_fd,(char *)ptlv,msglen);  
        ncs_log(WARN,"%s %d %s",__func__,pcfgresult->devId,pcfgresult->info);
        free(ptlv);
    }

    return 0;
}

int ncs_creat_client_un(struct ncs_object *ncs)
{
    if(!ncs)
        return -1;
    
    if((ncs->client_fd = ncs_udp_client_un(
        UNIX_CLIENT_PATH,UNIX_SERV_PATH)) < 0)
    {
        ncs_log(ERR,"%s create ncs unix client error",__func__);
        return -1;
    }
    
    evutil_make_socket_nonblocking(ncs->client_fd);
    ncs->ncs_client_recvev = event_new(ncs->g_base,
        ncs->client_fd,(EV_READ |EV_PERSIST),ncs->ncs_client_recv,ncs);
    if(!ncs->ncs_client_recvev)
    {
        ncs_log(ERR,"%s create new ncs_client_recv event error",__func__);
        return -1;
    }
    
    event_add(ncs->ncs_client_recvev,NULL); 

    return 0;
}

void ncs_client_recv(int fd,short event,void *arg)
{
    int bytes;
    char buff[BUFF_MAX];
    MSG_FUNC func;
    struct msg_hdr *pmsg;

    if(!arg || !(event & EV_READ))
        return;
    
    bytes=read(fd,&buff,BUFF_MAX);
    if(0>bytes)
    {
        ncs_log(ERR,"%s read ncs client message error %s",
                __func__,strerror(errno));
        return;
    }
    else if(0==bytes)
    {
        ncs_log(WARN,"%s read ncs client byte message",__func__);
        return;
    }
    
    pmsg = (struct msg_hdr *)buff;
    if(pmsg->type <= __NCS_CLIENT_MSGTYPE_NULL__
        || pmsg->type >= __NCS_CLIENT_MSGTYPE_MAX__
        || pmsg->len <= 0)
    {
        ncs_log(ERR,"%s recv unknow message type(%d)",
                    __func__,pmsg->type);
        return;
    }
    
    ncs_log(INFO,"%s ncs servd recv ncs client message %d",__func__,pmsg->type);

    if(func=ncs_client_msg[pmsg->type].func)
        if(-1 == func(pmsg->type,arg,buff))
            ncs_log(ERR,"%s process ncs client message failure",__func__);

    return;
}



int ncs_msg_add(struct list *tlvList, int devID, char devType, char *outBuffer, short *pLength)

{
    struct cfgmsg_hdr cfgMsg;
    struct cfgmsg info;
    struct listnode *node;
    struct listnode *next;
    StTlvListNode *listnode = NULL;
    char *pi = outBuffer;
    short index = 0;
    
    if (NULL == tlvList || NULL == outBuffer 
        || NULL == pLength)
    {
        return -1;
    }
    
    cfgMsg.devType = devType;      
    cfgMsg.devId = devID;
    cfgMsg.cnt = tlvList->count;
    memcpy(pi, &cfgMsg, sizeof(cfgMsg));
    index += sizeof(cfgMsg);

    for (node = tlvList->head; node; node = next)
    {
        next = node->next;
        memset(&info, 0, sizeof(info));

        listnode= (StTlvListNode *)node->data;
        info.type = listnode->type;
        info.flag = CFG_FLAG_ADD;
        info.rc_id = listnode->rcID;

        memcpy(pi+index, &info, sizeof(info));
        index += sizeof(info);
    }
    
    *pLength = index;

    return 0;
}

int ncs_msg_logoff(struct list *tlvList, int devID, char chaID, char *outBuffer, short *pLength)
{
    struct logoffmsg logoffMsg;
    char *pi = outBuffer;
    
    if (NULL == tlvList || NULL == outBuffer 
        || NULL == pLength)
    {
        return -1;
    }
    memset(&logoffMsg, 0, sizeof(logoffMsg));
    logoffMsg.devID = devID;
    logoffMsg.chaID = chaID;

    memcpy(pi, &logoffMsg, sizeof(logoffMsg));
    *pLength = sizeof(logoffMsg);

    return 0;
}


